package com.bi.design.config;

import com.alibaba.fastjson.JSONArray;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import com.alibaba.fastjson.JSONObject;
import org.springframework.stereotype.Component;
import org.springframework.util.Base64Utils;
import org.springframework.web.client.RestTemplate;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 海康乐橙云平台工具类
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class ImouTools {
    private final static String ACCESS_TOKEN = "imou:cloud:device:accessToken:%s";
    private static final Map<String, String> CACHE = new ConcurrentHashMap<>();
    private final ImouCloudDeviceProperties imouCloudDeviceProperties;
    private final RestTemplate restTemplate;

    /**
     * 获取 AccessToken
     *
     * @return String AccessToken
     */
    public String getAccessToken() {
        String appId = imouCloudDeviceProperties.getAppId();
        String secret = imouCloudDeviceProperties.getAppSecret();
        String accessToken = CACHE.get(String.format(ACCESS_TOKEN, appId));
        if (StringUtils.isNotBlank(accessToken)) {
            return accessToken;
        }
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        HttpEntity<Map<String, Object>> entity = new HttpEntity<>(paramsInit(new HashMap<>()), headers);
        JSONObject object = restTemplate.exchange(String.format(imouCloudDeviceProperties.getGetAccessTokenUrl(), appId, secret), HttpMethod.POST, entity, JSONObject.class).getBody();
        JSONObject result = object.getJSONObject("result");
        if ("0".equals(result.getString("code"))) {
            JSONObject data = result.getJSONObject("data");
            accessToken = data.getString("accessToken");
            // 防止抖动，默认降低300s 就获取新的token
            CACHE.put(String.format(ACCESS_TOKEN, appId), accessToken);
            return accessToken;
        }
        log.info(">>>>>>getAccessToken>>>>>>>:{}", object);
        throw new RuntimeException("accessToken 获取失败!");
    }


    /**
     * 根据序列号获取直播地址和直播状态
     *
     * @return 列表
     */
    public JSONArray getLiveStreamInfo() {
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        Map<String, Object> paramsMap = new HashMap<>();
        paramsMap.put("deviceId", imouCloudDeviceProperties.getDeviceId());
        paramsMap.put("channelId", 0);
        paramsMap.put("token", getAccessToken());
        HttpEntity<Map<String, Object>> entity = new HttpEntity<>(paramsInit(paramsMap), headers);
        JSONObject object = restTemplate.exchange(imouCloudDeviceProperties.getGetLiveStreamInfoUrl(), HttpMethod.POST, entity, JSONObject.class).getBody();
        JSONObject result = object.getJSONObject("result");
        if ("0".equals(result.getString("code"))) {
            return result.getJSONObject("data").getJSONArray("streams");
        }
        log.error(">>>>>>getLiveStreamInfo>>>>>>>:{}", object);
        throw new RuntimeException("根据序列号获取直播地址和直播状态获取失败!");
    }


    /**
     * 设备抓图
     *
     * @return String
     */
    public String setDeviceSnap() {
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        Map<String, Object> paramsMap = new HashMap<>();
        paramsMap.put("deviceId", imouCloudDeviceProperties.getDeviceId());
        paramsMap.put("channelId", 0);
        paramsMap.put("token", getAccessToken());
        HttpEntity<Map<String, Object>> entity = new HttpEntity<>(paramsInit(paramsMap), headers);
        JSONObject object = restTemplate.exchange("https://openapi.lechange.cn/openapi/setDeviceSnapEnhanced", HttpMethod.POST, entity, JSONObject.class).getBody();
        JSONObject result = object.getJSONObject("result");
        if ("0".equals(result.getString("code"))) {
            return result.getJSONObject("data").getString("url");
        }
        log.error(">>>>>>setDeviceSnap>>>>>>>:{}", object);
        throw new RuntimeException("设备抓图失败!");
    }


    /**
     * 初始化api参数
     *
     * @param paramsMap 请求参数集合
     * @return 包装后的请求参数
     */
    private Map<String, Object> paramsInit(Map<String, Object> paramsMap) {
        String appId = imouCloudDeviceProperties.getAppId();
        String appSecret = imouCloudDeviceProperties.getAppSecret();
        long time = System.currentTimeMillis() / 1000;
        String nonce = UUID.randomUUID().toString();
        String id = UUID.randomUUID().toString();

        StringBuilder paramString = new StringBuilder();
        paramString.append("time:").append(time).append(",");
        paramString.append("nonce:").append(nonce).append(",");
        paramString.append("appSecret:").append(appSecret);

        String sign = "";
        // 计算MD5得值
        try {
            sign = DigestUtils.md5Hex(paramString.toString().trim().getBytes(StandardCharsets.UTF_8));
        } catch (Exception e) {
            throw new RuntimeException("imou md5摘要失败!");
        }
        Map<String, Object> systemMap = new HashMap<String, Object>();
        systemMap.put("ver", "1.0");
        systemMap.put("sign", sign);
        systemMap.put("appId", appId);
        systemMap.put("nonce", nonce);
        systemMap.put("time", time);
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("system", systemMap);
        map.put("params", paramsMap);
        map.put("id", id);
        return map;
    }
}
